// OpenGLCase.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "OpenGLCase0.h"

// Shaders
const GLchar* vertexShaderSource = "#version 330 core\n"
"layout (location = 0) in vec3 position;\n"
"void main()\n"
"{\n"
"gl_Position = vec4(position.x, position.y, position.z, 1.0);\n"
"}\0";
const GLchar* fragmentShaderSourceOrange = "#version 330 core\n"
"out vec4 color;\n"
"void main()\n"
"{\n"
"color = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
"}\n\0";

const GLchar* fragmentShaderSourceYellow = "#version 330 core\n"
"out vec4 color;\n"
"void main()\n"
"{\n"
"color = vec4(1.0f, 1.0f, 0.0f, 1.0f);\n"
"}\n\0";

int width = 800;
int height = 600;



void vaoVboDraw(GLuint shaderProgram);
void vaoVboEboDraw(GLuint shaderProgram);

// 准备章节，绘制四边形
void runCase0()
{

	glfwInit();
	GLFWwindow* winodw = glfwCreateWindow(width, height, "ConsoleOpenGL", NULL, NULL);
	if (!winodw) {
		glfwTerminate();
		return;
	}

	glfwMakeContextCurrent(winodw);

	if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
		return;
	}

	glViewport(0, 0, width, height);

	GLuint shaderProgram = ShaderBuilder().buildShaderProgram(vertexShaderSource, fragmentShaderSourceOrange);

	while (!glfwWindowShouldClose(winodw)) {
		// 检查事件
		glfwPollEvents();

		//渲染指令
        glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT);



		// 使用 VAO + VBO 绘制四边形
		//vaoVboDraw(shaderProgram);
		// 使用 VAO + VBO + EBO 绘制四边形
		vaoVboEboDraw(shaderProgram);

		// 交换缓冲
		glfwSwapBuffers(winodw);

	}
	glfwTerminate();
}


// 方法一：VAO + VBO 绘制四边形
void vaoVboDraw(GLuint shaderProgram) {

	// 渲染之前 VAO/VBO 的绑定生成

	// 顶点数据
	GLfloat vertices[] = {
		// 第一个三角形
		 0.5f,  0.5f, 0.0f, // 右上
		 0.5f, -0.5f, 0.0f, // 右下
		-0.5f, -0.5f, 0.0f, // 左下
		// 第二个三角形
		-0.5f, -0.5f, 0.0f, // 左下
		 0.5f,  0.5f, 0.0f, // 右上
		-0.5f,  0.5f, 0.0f  // 左上
	};

	// 生成立方体的VAO、VBO
	GLuint VBO, VAO;
	glGenBuffers(1, &VBO);
	glGenVertexArrays(1, &VAO);
	// 绑定AVO
	glBindVertexArray(VAO);
	// 绑定VBO并传入顶点数据
	glBindBuffer(GL_ARRAY_BUFFER, VBO); 
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
	// 设置顶点属性指针
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
	glEnableVertexAttribArray(0);
	// 解绑VBO
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	// 解绑VAO
	glBindVertexArray(0);

	// 渲染时
	// 使用之前链接好的着色器程序
	glUseProgram(shaderProgram);
	// 绑定VAO
	glBindVertexArray(VAO);
	// 用VAO绘制四边形
	glDrawArrays(GL_TRIANGLES, 0, 6);
}


// 方法二：VAO + VBO + EBO 绘制四边形
void vaoVboEboDraw(GLuint shaderProgram) {

	// 渲染之前 VAO/VBO/EBO 的绑定生成

	// 顶点数据
	float vertices[] = {
		 1.0f,  0.5f, 0.0f, // 右上
		 0.5f, -0.5f, 0.0f, // 右下
		-0.5f, -0.5f, 0.0f, // 左下
		-0.5f,  0.5f, 0.0f  // 左上
	};

	// 索引数据（注意这里是从0开始的）
	unsigned int indices[] = {
		0, 1, 3,	 // 第一个三角形
		1, 2, 3  // 第二个三角形
	};

	// 生成立方体的VAO、VBO 和 EBO
	unsigned int VBO, VAO, EBO;
	glGenVertexArrays(1, &VAO);
	glGenBuffers(1, &VBO);
	glGenBuffers(1, &EBO);
	// 绑定AVO
	glBindVertexArray(VAO);
	// 绑定VBO并传入顶点数据
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
	// 绑定EBO并传入索引数据
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STATIC_DRAW);
	// 设置顶点属性指针
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
	glEnableVertexAttribArray(0);
	// 解绑VBO
	glBindBuffer(GL_ARRAY_BUFFER, 0);
	// 注意不要解绑EBO,因为EBO存储在VAO中
	//glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
	// 解绑VAO
	glBindVertexArray(0);


	// 渲染时
	// 使用之前链接好的着色器程序
	glUseProgram(shaderProgram);
	// 绑定VAO（实际上不需要每次绑定）
	glBindVertexArray(VAO);
	// 用EBO绘制四边形
	glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}



// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

// 入门使用技巧: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件，或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来，若要再次打开此项目，请转到“文件”>“打开”>“项目”并选择 .sln 文件
